const { src, dest, parallel, series, watch } = require('gulp')

const del = require('del')
const browserSync = require('browser-sync')

const loadPlugins = require("gulp-load-plugins")
const plugins = loadPlugins()

const bs = browserSync.create()
const cwd = process.cwd()//当前项目目录
let config = {
  //default config
  build:{
    src:'src',
    dist:'dist',
    temp:'temp',
    public:'public',
    paths:{
      styles:'assets/styles/*.scss',
      scripts:'assets/scripts/*.js',
      pages:'*.html',
      images:'assets/images/**',
      fonts:'assets/fonts/**'
    }
  }
}
try{
  const loadConfig = require(`${cwd}/pages.config.js`) //项目数据通过pages.config.js写入,有可能为空，加个trycatch
  config = Object.assign({},config,loadConfig)
}catch(e){}

const clean = ()=>{
  return del([config.build.dist,config.build.temp])
}

const style = ()=>{ //gulp-sass
  return src(config.build.paths.styles,{base:config.build.src,cwd:config.build.src}) //'src/assets/styles/*.scss' | 'src' | cwd为配置的当前目录
    .pipe(plugins.sass({outputStyle:'expanded'})) //展开
    .pipe(dest(config.build.temp)) //'temp'
    .pipe(bs.reload({ stream:true } )) 
}

const script = ()=>{ //gulp-babel @babel/core @babel/preset-env
  return src(config.build.paths.scripts,{base:config.build.src,cwd:config.build.src})
    .pipe(plugins.babel({presets:[require('@babel/preset-env')]})) //'@babel/preset-env'不能添加相对路径！不然外面使用时找不到！
    .pipe(dest(config.build.temp))
    .pipe(bs.reload({ stream:true } ))
}

const page = ()=>{ //gulp-swig
  return src(config.build.paths.pages,{base:config.build.src,cwd:config.build.src}) //'src/*.html',{base:'src'}
    .pipe(plugins.swig({data:config.data,defaults:{cache:false}})) //data项目去定义，不要封装在模块内，封装的模块只是使用项目的数据，数据从外部传入
    .pipe(dest(config.build.temp))
    .pipe(bs.reload({ stream:true } ))
}

const image = ()=>{ //gulp-imagemin 压缩
  return src(config.build.paths.images,{base:config.build.src,cwd:config.build.src})
    .pipe(plugins.imagemin()) 
    .pipe(dest(config.build.dist))
}

const font = ()=>{
  return src(config.build.paths.fonts,{base:config.build.src,cwd:config.build.src})
    .pipe(plugins.imagemin())
    .pipe(dest(config.build.dist))
}

const extra = ()=>{
  return src('**',{base:config.build.public,cwd:config.build.public})//'public/**',{base:'public'}
    .pipe(dest(config.build.dist))
}

const serve = ()=>{
  watch(config.build.paths.styles,{cwd:config.build.src},style)////通配符，任务
  watch(config.build.paths.scripts,{cwd:config.build.src},script)
  watch(config.build.paths.pages,{cwd:config.build.src},page)
  watch([
    config.build.paths.images,
    config.build.paths.fonts,
  ],{cwd:config.build.src},bs.reload)  //browsersync提供的reload方法，一个任务就是一个方法,上面三个放在了pipe中

  watch('**',{cwd:config.build.public},bs.reload)

  bs.init({
    notify:false,
    port:2080,
    // files:"dist/**" //哪些文件改变自动更新浏览器
    server:{
      baseDir:[config.build.temp,config.build.src,config.build.public],//监视的根目录按数组顺序查找
      routes:{
        '/node_modules':'node_modules'
      }
    }
  }) 
}

const useref = ()=>{ //gulp-useref gulp-if  合并生成html中找不到的文件，
  return src(config.build.paths.pages,{base:config.build.temp,cwd:config.build.temp})
    .pipe(plugins.useref({ searchPath:['..','.'] }))//查找路径从cwd下
    .pipe(plugins.if(/\.js$/,plugins.uglify())) //gulp-uglify
    .pipe(plugins.if(/\.css$/,plugins.cleanCss())) //gulp-clean-css
    .pipe(plugins.if(/\.html$/,plugins.htmlmin({ collapseWhitespace: true, minifyCSS:true,minifyJS:true }))) //gulp-htmlmin
    .pipe(dest(config.build.dist))
}

const compile = parallel(style,script,page)

const build = series(
  clean,
  parallel(
    series(compile,useref),
    image,
    font,
    extra
  )
) 

const develop = series(compile,serve)

module.exports = {
  // style,  //注意。"_"开头会忽略
  // script,
  // page,
  // image,
  // font,
  // serve,
  // useref, //将HTML引用的多个CSS和JS合并起来
  // compile,
  clean,
  build,
  develop
}